//@ts-nocheck

import { getToken } from "./cache/cookies"
import { encryptMsg, decryptMsg } from '@/utils/decrypt'
import uploadFile from '@/api/upload'
import { useUserStoreHook } from "@/store/modules/user"

var socket = null
var lockReconnect = false
var timeout = 30 * 1000
var timeoutObj = null
var serverTimeoutObj = null
var timeoutnum = null

// 重试次数
var retryCount = 0
// 存储临时消息
const cacheMsgList = {}

// 如果有token，并且socket为null， 则连接socket
const checkWebSocket = () => {
  const token = getToken()
  if (token && socket === null) {
    initWebSocket()
  }
}

const initWebSocket = async() => {
  if ('WebSocket' in window) {
    // console.log('initwebsocket: ')
    const token = getToken()
    if (token) {
      const wsUrl = 'ws://10.191.72.252:8888/' + token
      // console.log(wsUrl)
      socket = new WebSocket(wsUrl)

      socket.onerror = webSocketOnError
      socket.onmessage = webSocketOnMessage
      socket.onclose = closeWebSocket
      socket.onopen = openWebSocket
    } else {
      // console.log('未登录，socket不创建')
      close()
    }
  } else {
    console.log('浏览器不支持')
  }
}

const openWebSocket = () => {
  // 连接成功吗
  if (socket && socket.readyState === 1) {
    console.log('socket连接成功。。。')
    // 判断cacheMsgList是否有值,循环发送
    for (const key in cacheMsgList) {
      // 判断，已经失败的，就不要再自动发送了，
      if (cacheMsgList[key].status !== 'failed') {
        socket.send(JSON.stringify(cacheMsgList[key]))
      }
    }
  }
  start()
}

const start = () => {
  retryCount = 0

  timeoutObj && clearTimeout(timeoutObj)
  serverTimeoutObj && clearTimeout(serverTimeoutObj)
  timeoutObj = setTimeout(() => {
    if (socket && socket.readyState === 1) {
      //
      sendPing()
    } else {
      // 重新连接
      // console.log('为什么重新连接了 start timeout')
      console.log(socket)
      reconnect()
    }
    serverTimeoutObj = setTimeout(function() {
      // console.log('超时关闭了？？？')
      // 超时关闭
      // 这么久了, 都走到这里来了
      // 说明没有重置计时器 ， 服务端没有给返回消息， 那就毁灭吧
      close()
    }, timeout)
  }, timeout)
}

const reconnect = () => {
  if (lockReconnect) {
    return
  }

  if (retryCount >= 10) {
    return // 重试次数超出限制
  }

  retryCount = retryCount + 1

  // 重新连接, 判断登录状态
  const token = getToken()
  if (token) {
    console.log('重新连接socket')
    lockReconnect = true

    timeoutnum && clearTimeout(timeoutnum)
    timeoutnum = setTimeout(function() {
      initWebSocket()
      lockReconnect = false
    }, 10000)
  } else {
    // 没有token, 关闭
    close()
  }
}

const reset = () => {
  clearTimeout(timeoutObj)
  clearTimeout(serverTimeoutObj)
  start()
}

// // 发送消息（to_id: '', message: ''）
// const sendWebSocket = (e) => {
//   const str = JSON.stringify(e)
//   socket.send(str)
// }

// 发送心跳
const sendPing = () => {
  const heart = {
    type: 0,
    content: 'ping'
  }
  socket.send(JSON.stringify(heart))
}

// 上传文件
const uploadFileFirst = (file, successFunc, failedFunc) => {
  uploadFile(file).then(val => {
    // 上传成功
    const url = val.host + '/' + val.path
    successFunc(url)
  }).catch(() => {
    // 上传失败 也发送一下
    failedFunc()
  })
}

// 发送用户消息
const sendUserMessage = (sendId, toId, message) => {
  return sendMessage(sendId, toId, message, 1)
}

// 发送群消息
const sendGroupMessage = (sendId, toId, message) => {
  return sendMessage(sendId, `${toId}`, message, 11)
}

// 发送群图片
const sendGroupImageMsg = (sendId, toId, file) => {
  return sendImageMsg(sendId, `${toId}`, file, 11)
}

// 发送私聊图片
const sendUserImageMsg = (sendId, toId, file) => {
  return sendImageMsg(sendId, `${toId}`, file, 1)
}

// 发送图片、文件等
const sendImageMsg = (sendId, toId, file, type) => {
  const msg = {
    type: type,
    sender_id: sendId,
    receiver_id: toId,
    message_type: 'IMG',
    content: window.URL.createObjectURL(file),
    tmpFile: file
  }
  const now = Date.now()
  msg['unique_id'] = `${now}`
  msg['sent_at'] = now
  msg['status'] = 'sending'
  msg['upload'] = 0

  const cacheMsg = { ...msg } // 复制对象、保存
  cacheMsgList[msg.unique_id] = cacheMsg

  uploadFileFirst(file, function(url) {
    // 成功后执行
    const toMsg = { ...msg }
    toMsg.content = url
    toMsg.upload = 1
    toMsg.tmpFile = null
    cacheMsgList[msg.unique_id] = toMsg

    if (socket && socket.readyState === 1) {
      console.log('发送。。' + JSON.stringify(toMsg))

      socket.send(JSON.stringify(toMsg))
    } else {
      // 不能通信、先去重连
      reconnect()
    }
    // 做一个超时，如果10s后 还在 cacheMsgList中，则表示发送失败
    setTimeout(() => {
      if (cacheMsgList[msg.unique_id]) {
      // 表示发送失败
        cacheMsgList[msg.unique_id].status = 'failed'
        onMessageSendFailed(cacheMsgList[msg.unique_id])
      }
    }, 10000)
  }, function() {
    // 失败执行、、、
    // 上传失败 也发送一下
    cacheMsgList[msg.unique_id].upload = -1
    onMessageSendFailed(cacheMsgList[msg.unique_id])
  })

  // console.log('发送消息 ----------------- ')
  // console.log(JSON.stringify(msg))
  return msg
}

// 发送消息
// （0-心跳， 1-正常消息, 2-消息状态更新， 3-自己发的消息, 4, 用户上线状态更新）
// 11-群消息 33-自己发的群消息
const sendMessage = (sendId, toId, message, type) => {
  const msg = {
    type: type,
    sender_id: sendId,
    receiver_id: toId,
    message_type: 'TEXT',
    content: message
  }
  const now = Date.now()
  msg['unique_id'] = `${now}`
  msg['sent_at'] = now
  msg['status'] = 'sending'

  const toMsg = { ...msg }
  if (message.length > 0) {
    const vText = encryptMsg(message, `${msg.unique_id}${sendId}`)
    toMsg.content = vText

    // const deText = decryptMsg(vText, `${msg.unique_id}${sendId}`)
    // console.log(deText)
  }

  cacheMsgList[msg.unique_id] = msg

  // console.log('发送消息 ----------------- ')
  // console.log(JSON.stringify(msg))

  // 做一个超时，如果10s后 还在 cacheMsgList中，则表示发送失败
  setTimeout(() => {
    if (cacheMsgList[msg.unique_id]) {
      // 表示发送失败
      cacheMsgList[msg.unique_id].status = 'failed'
      onMessageSendFailed(cacheMsgList[msg.unique_id])
    }
  }, 10000)

  if (socket && socket.readyState === 1) {
    socket.send(JSON.stringify(toMsg))
  } else {
    // 不能通信、先去重连
    reconnect()
  }
  return msg
}

// 再次点击发送失败消息
function sendFailedMessageAgain(item) {
  const msg = cacheMsgList[item.unique_id]
  if (msg) {
    item.status = 'sending'
    // 如果是图片、并且没有上传成功，先去上传图片， 再回来
    if (item.message_type === 'IMG' && item.upload !== 1) {
      const that = this
      uploadFileFirst(item.tmpFile, (url) => {
        item.content = url
        item.tmpFile = null
        item.upload = 1
        that.sendFailedMessageAgain(item)
      }, () => {})
      return
    }

    if (socket && socket.readyState === 1) {
      socket.send(JSON.stringify(msg))
    } else {
      // 去重连吧
      cacheMsgList[item.unique_id].status = 'sending'
      reconnect()
    }
  }
}

// 传递发送失败的消息
function onMessageSendFailed(msg) {
  window.dispatchEvent(
    new CustomEvent('onmessageWSFailed', {
      detail: {
        data: msg
      }
    })
  )
}

// 接收消息
function receivedMessage(msgId) {
  updateMessage(msgId, 'Received')
}

// 读消息
function readMessage(msgId) {
  updateMessage(msgId, 'Read')
}

// 更新消息状态 Received、Unread、Read、Recalled
// 已接收、未读、已读、撤回
const updateMessage = (msgId, status) => {
  const msg = {
    type: 2,
    message_id: msgId,
    status: status
  }
  console.log('更新消息: ' + JSON.stringify(msg))
  socket.send(JSON.stringify(msg))
}

const webSocketOnError = (e) => {
  // console.log('异常')
  // console.log(e)
  if (!socket) {
    return
  }
  // console.log(socket.readyState)
  if (socket.readyState === 3) {
    close()
  } else {
    initWebSocket()
    reconnect()
  }
}

// （0-心跳， 1-正常消息, 2-消息状态更新， 3-自己发的消息, 4, 用户上线状态更新）
// 11群消息 33自己发的群消息
const webSocketOnMessage = (e) => {
  const obj = e?.data
  if (obj) {
    // 收到消息后 说明连接正常 重置计时器，
    // reset() // 改为收到心跳再重置下次心跳时间

    const item = JSON.parse(obj)

    if (item.type === 0) {
      // console.log('心跳~')
      // if (item.content === 'pong') {
      // 服务端pong的，收到了
      // }
      reset()
      return
    }

    // console.log('收到消息 ----------------- ')
    // console.log(JSON.stringify(item))

    if (item.type === 1) {
      if (item.message_type === 'TEXT' && item.content && item.content.length > 0) {
        const vText = decryptMsg(item.content, `${item.unique_id}${item.sender_id}`)
        item.content = vText
      }

      // 发送消息内容
      window.dispatchEvent(
        new CustomEvent('onmessageWS', {
          detail: {
            data: item
          }
        })
      )
      return
    } else if (item.type === 11) {
      if (item.message_type === 'TEXT' && item.content && item.content.length > 0) {
        const vText = decryptMsg(item.content, `${item.unique_id}${item.sender_id}`)
        item.content = vText
      }

      // 发送消息内容
      window.dispatchEvent(
        new CustomEvent('onmessageGroupWS', {
          detail: {
            data: item
          }
        })
      )
      return
    } else if (item.type === 2) {
      // 消息状态更新、已读、未读、撤回等
      window.dispatchEvent(
        new CustomEvent('getSocketMessageStatusChange', {
          detail: {
            data: item
          }
        })
      )
      return
    } else
    if (item.type === 3 || item.type === 33) {
      // 自己发送的消息
      if (item.unique_id && item.unique_id.length > 0 && cacheMsgList[item.unique_id]) {
        delete cacheMsgList[item.unique_id]
      }

      window.dispatchEvent(
        new CustomEvent('getSocketMessageStatusChange', {
          detail: {
            data: item
          }
        })
      )
      return
    } else
    if (item.type === 4) {
      // 其它用户上线状态更新
      window.dispatchEvent(
        new CustomEvent('onmessageOtherOnline', {
          detail: {
            data: item
          }
        })
      )
      return
    } else
    if (item.type === 20) {
      // 被拉入了新群
      // 刷新一下群信息
      const groupId = item.sender_id
      window.dispatchEvent(
        new CustomEvent('joinedNewGroupWS', {
          detail: {
            data: groupId
          }
        })
      )
      return
    }
    window.dispatchEvent(
      new CustomEvent('onmessageWS', {
        detail: {
          data: item
        }
      })
    )
  }
}

const closeWebSocket = () => {
  // console.log('关闭了 ？？？ 吗')
  reconnect()
}

const close = () => {
  // console.log('手动执行关闭方法---')
  if (socket) {
    // console.log('怎么关闭了 socket')
    socket.close()
    socket = null
  }
}

// const webFunc = 

export {
  checkWebSocket,
  initWebSocket,
  sendUserMessage,
  sendGroupMessage,
  sendUserImageMsg,
  sendGroupImageMsg,
  sendFailedMessageAgain,
  receivedMessage,
  readMessage,
  webSocketOnMessage,
  close
}
